package com.llu.sha;

import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;

public class DigitalSignatureExample {
    public static void main(String[] args) throws Exception {
        String data = "Hello, World!";

        // 生成RSA密钥对
        KeyPair keyPair = generateRSAKeyPair();

        // 生成数字签名
        String signature = generateDigitalSignature(data, keyPair.getPrivate());
        System.out.println("Signature (Base64): " + signature);

        // 验证数字签名
        boolean isVerified = verifyDigitalSignature(data, signature, keyPair.getPublic());
        System.out.println("Signature Verified: " + isVerified);
    }

    /**
     * 生成RSA密钥对
     *
     * @return 生成的密钥对
     * @throws NoSuchAlgorithmException 如果算法不可用
     */
    public static KeyPair generateRSAKeyPair() throws NoSuchAlgorithmException {
        // 获取密钥生成器实例
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        // 初始化密钥生成器为2048位RSA密钥
        keyPairGenerator.initialize(2048);
        // 生成密钥对
        return keyPairGenerator.generateKeyPair();
    }

    public static String generateDigitalSignature(String data, PrivateKey privateKey) throws Exception {
        // 获取SHA-256和RSA签名实例
        Signature signature = Signature.getInstance("SHA256withRSA");

        // 初始化签名对象
        signature.initSign(privateKey);

        // 更新数据
        signature.update(data.getBytes(StandardCharsets.UTF_8));

        // 生成签名
        byte[] signatureBytes = signature.sign();

        // 将签名字节数组转换为Base64编码字符串
        return Base64.getEncoder().encodeToString(signatureBytes);
    }

    public static boolean verifyDigitalSignature(String data, String signature, PublicKey publicKey) throws Exception {
        // 获取SHA-256和RSA签名实例
        Signature sig = Signature.getInstance("SHA256withRSA");

        // 初始化签名对象
        sig.initVerify(publicKey);

        // 更新数据
        sig.update(data.getBytes(StandardCharsets.UTF_8));

        // 验证签名
        byte[] signatureBytes = Base64.getDecoder().decode(signature);
        return sig.verify(signatureBytes);
    }
}

